﻿/**
 * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.md or http://ckeditor.com/license
 */

/**
 * @fileOverview The "toolbar" plugin. Renders the default toolbar interface in
 * the editor.
 */

(function () {
    var toolbox = function () {
        this.toolbars = [];
        this.focusCommandExecuted = false;
    };

    toolbox.prototype.focus = function () {
        for (var t = 0, toolbar; toolbar = this.toolbars[t++];) {
            for (var i = 0, item; item = toolbar.items[i++];) {
                if (item.focus) {
                    item.focus();
                    return;
                }
            }
        }
    };

    var commands = {
        toolbarFocus: {
            modes: {wysiwyg: 1, source: 1},
            readOnly: 1,

            exec: function (editor) {
                if (editor.toolbox) {
                    editor.toolbox.focusCommandExecuted = true;

                    // Make the first button focus accessible for IE. (#3417)
                    // Adobe AIR instead need while of delay.
                    if (CKEDITOR.env.ie || CKEDITOR.env.air)
                        setTimeout(function () {
                            editor.toolbox.focus();
                        }, 100);
                    else
                        editor.toolbox.focus();
                }
            }
        }
    };

    CKEDITOR.plugins.add('toolbar', {
        requires: 'button',
        lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%

        init: function (editor) {
            var endFlag;

            var itemKeystroke = function (item, keystroke) {
                var next, toolbar;
                var rtl = editor.lang.dir == 'rtl',
                    toolbarGroupCycling = editor.config.toolbarGroupCycling,
                    // Picking right/left key codes.
                    rightKeyCode = rtl ? 37 : 39,
                    leftKeyCode = rtl ? 39 : 37;

                toolbarGroupCycling = toolbarGroupCycling === undefined || toolbarGroupCycling;

                switch (keystroke) {
                    case 9: // TAB
                    case CKEDITOR.SHIFT + 9: // SHIFT + TAB
                        // Cycle through the toolbars, starting from the one
                        // closest to the current item.
                        while (!toolbar || !toolbar.items.length) {
                            toolbar = keystroke == 9 ? ((toolbar ? toolbar.next : item.toolbar.next) || editor.toolbox.toolbars[0]) : ((toolbar ? toolbar.previous : item.toolbar.previous) || editor.toolbox.toolbars[editor.toolbox.toolbars.length - 1]);

                            // Look for the first item that accepts focus.
                            if (toolbar.items.length) {
                                item = toolbar.items[endFlag ? (toolbar.items.length - 1) : 0];
                                while (item && !item.focus) {
                                    item = endFlag ? item.previous : item.next;

                                    if (!item)
                                        toolbar = 0;
                                }
                            }
                        }

                        if (item)
                            item.focus();

                        return false;

                    case rightKeyCode:
                        next = item;
                        do {
                            // Look for the next item in the toolbar.
                            next = next.next;

                            // If it's the last item, cycle to the first one.
                            if (!next && toolbarGroupCycling) next = item.toolbar.items[0];
                        }
                        while (next && !next.focus);

                        // If available, just focus it, otherwise focus the
                        // first one.
                        if (next)
                            next.focus();
                        else
                            // Send a TAB.
                            itemKeystroke(item, 9);

                        return false;
                    case 40: // DOWN-ARROW
                        if (item.button && item.button.hasArrow) {
                            // Note: code is duplicated in plugins\richcombo\plugin.js in keyDownFn().
                            editor.once('panelShow', function (evt) {
                                evt.data._.panel._.currentBlock.onKeyDown(40);
                            });
                            item.execute();
                        } else {
                            // Send left arrow key.
                            itemKeystroke(item, keystroke == 40 ? rightKeyCode : leftKeyCode);
                        }
                        return false;
                    case leftKeyCode:
                    case 38: // UP-ARROW
                        next = item;
                        do {
                            // Look for the previous item in the toolbar.
                            next = next.previous;

                            // If it's the first item, cycle to the last one.
                            if (!next && toolbarGroupCycling) next = item.toolbar.items[item.toolbar.items.length - 1];
                        }
                        while (next && !next.focus);

                        // If available, just focus it, otherwise focus the
                        // last one.
                        if (next)
                            next.focus();
                        else {
                            endFlag = 1;
                            // Send a SHIFT + TAB.
                            itemKeystroke(item, CKEDITOR.SHIFT + 9);
                            endFlag = 0;
                        }

                        return false;

                    case 27: // ESC
                        editor.focus();
                        return false;

                    case 13: // ENTER
                    case 32: // SPACE
                        item.execute();
                        return false;
                }
                return true;
            };

            editor.on('uiSpace', function (event) {
                if (event.data.space != editor.config.toolbarLocation)
                    return;

                // Create toolbar only once.
                event.removeListener();

                editor.toolbox = new toolbox();

                var labelId = CKEDITOR.tools.getNextId();

                var output = [
                    '<span id="', labelId, '" class="cke_voice_label">', editor.lang.toolbar.toolbars, '</span>',
                    '<span id="' + editor.ui.spaceId('toolbox') + '" class="cke_toolbox" role="group" aria-labelledby="', labelId, '" onmousedown="return false;">'];

                var expanded = editor.config.toolbarStartupExpanded !== false,
                    groupStarted, pendingSeparator;

                // If the toolbar collapser will be available, we'll have
                // an additional container for all toolbars.
                if (editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE)
                    output.push('<span class="cke_toolbox_main"' + (expanded ? '>' : ' style="display:none">'));

                var toolbars = editor.toolbox.toolbars,
                    toolbar = getToolbarConfig(editor);

                for (var r = 0; r < toolbar.length; r++) {
                    var toolbarId,
                        toolbarObj = 0,
                        toolbarName,
                        row = toolbar[r],
                        items;

                    // It's better to check if the row object is really
                    // available because it's a common mistake to leave
                    // an extra comma in the toolbar definition
                    // settings, which leads on the editor not loading
                    // at all in IE. (#3983)
                    if (!row)
                        continue;

                    if (groupStarted) {
                        output.push('</span>');
                        groupStarted = 0;
                        pendingSeparator = 0;
                    }

                    if (row === '/') {
                        output.push('<span class="cke_toolbar_break"></span>');
                        continue;
                    }

                    items = row.items || row;

                    // Create all items defined for this toolbar.
                    for (var i = 0; i < items.length; i++) {
                        var item = items[i],
                            canGroup;

                        if (item) {
                            if (item.type == CKEDITOR.UI_SEPARATOR) {
                                // Do not add the separator immediately. Just save
                                // it be included if we already have something in
                                // the toolbar and if a new item is to be added (later).
                                pendingSeparator = groupStarted && item;
                                continue;
                            }

                            canGroup = item.canGroup !== false;

                            // Initialize the toolbar first, if needed.
                            if (!toolbarObj) {
                                // Create the basic toolbar object.
                                toolbarId = CKEDITOR.tools.getNextId();
                                toolbarObj = {id: toolbarId, items: []};
                                toolbarName = row.name && (editor.lang.toolbar.toolbarGroups[row.name] || row.name);

                                // Output the toolbar opener.
                                output.push('<span id="', toolbarId, '" class="cke_toolbar"', (toolbarName ? ' aria-labelledby="' + toolbarId + '_label"' : ''), ' role="toolbar">');

                                // If a toolbar name is available, send the voice label.
                                toolbarName && output.push('<span id="', toolbarId, '_label" class="cke_voice_label">', toolbarName, '</span>');

                                output.push('<span class="cke_toolbar_start"></span>');

                                // Add the toolbar to the "editor.toolbox.toolbars"
                                // array.
                                var index = toolbars.push(toolbarObj) - 1;

                                // Create the next/previous reference.
                                if (index > 0) {
                                    toolbarObj.previous = toolbars[index - 1];
                                    toolbarObj.previous.next = toolbarObj;
                                }
                            }

                            if (canGroup) {
                                if (!groupStarted) {
                                    output.push('<span class="cke_toolgroup" role="presentation">');
                                    groupStarted = 1;
                                }
                            } else if (groupStarted) {
                                output.push('</span>');
                                groupStarted = 0;
                            }

                            function addItem(item) {
                                var itemObj = item.render(editor, output);
                                index = toolbarObj.items.push(itemObj) - 1;

                                if (index > 0) {
                                    itemObj.previous = toolbarObj.items[index - 1];
                                    itemObj.previous.next = itemObj;
                                }

                                itemObj.toolbar = toolbarObj;
                                itemObj.onkey = itemKeystroke;

                                // Fix for #3052:
                                // Prevent JAWS from focusing the toolbar after document load.
                                itemObj.onfocus = function () {
                                    if (!editor.toolbox.focusCommandExecuted)
                                        editor.focus();
                                };
                            }

                            if (pendingSeparator) {
                                addItem(pendingSeparator);
                                pendingSeparator = 0;
                            }

                            addItem(item);
                        }
                    }

                    if (groupStarted) {
                        output.push('</span>');
                        groupStarted = 0;
                        pendingSeparator = 0;
                    }

                    if (toolbarObj)
                        output.push('<span class="cke_toolbar_end"></span></span>');
                }

                if (editor.config.toolbarCanCollapse)
                    output.push('</span>');

                // Not toolbar collapser for inline mode.
                if (editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE) {
                    var collapserFn = CKEDITOR.tools.addFunction(function () {
                        editor.execCommand('toolbarCollapse');
                    });

                    editor.on('destroy', function () {
                        CKEDITOR.tools.removeFunction(collapserFn);
                    });

                    editor.addCommand('toolbarCollapse', {
                        readOnly: 1,
                        exec: function (editor) {
                            var collapser = editor.ui.space('toolbar_collapser'),
                                toolbox = collapser.getPrevious(),
                                contents = editor.ui.space('contents'),
                                toolboxContainer = toolbox.getParent(),
                                contentHeight = parseInt(contents.$.style.height, 10),
                                previousHeight = toolboxContainer.$.offsetHeight,
                                minClass = 'cke_toolbox_collapser_min',
                                collapsed = collapser.hasClass(minClass);

                            if (!collapsed) {
                                toolbox.hide();
                                collapser.addClass(minClass);
                                collapser.setAttribute('title', editor.lang.toolbar.toolbarExpand);
                            } else {
                                toolbox.show();
                                collapser.removeClass(minClass);
                                collapser.setAttribute('title', editor.lang.toolbar.toolbarCollapse);
                            }

                            // Update collapser symbol.
                            collapser.getFirst().setText(collapsed ? '\u25B2' : // BLACK UP-POINTING TRIANGLE
                                '\u25C0'); // BLACK LEFT-POINTING TRIANGLE

                            var dy = toolboxContainer.$.offsetHeight - previousHeight;
                            contents.setStyle('height', (contentHeight - dy) + 'px');

                            editor.fire('resize');
                        },

                        modes: {wysiwyg: 1, source: 1}
                    });

                    editor.setKeystroke(CKEDITOR.ALT + (CKEDITOR.env.ie || CKEDITOR.env.webkit ? 189 : 109) /*-*/, 'toolbarCollapse');

                    output.push('<a title="' + (expanded ? editor.lang.toolbar.toolbarCollapse : editor.lang.toolbar.toolbarExpand)
                        + '" id="' + editor.ui.spaceId('toolbar_collapser')
                        + '" tabIndex="-1" class="cke_toolbox_collapser');

                    if (!expanded)
                        output.push(' cke_toolbox_collapser_min');

                    output.push('" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')">', '<span class="cke_arrow">&#9650;</span>', // BLACK UP-POINTING TRIANGLE
                        '</a>');
                }

                output.push('</span>');
                event.data.html += output.join('');
            });

            editor.on('destroy', function () {

                if (this.toolbox) {
                    var toolbars,
                        index = 0,
                        i, items, instance;
                    toolbars = this.toolbox.toolbars;
                    for (; index < toolbars.length; index++) {
                        items = toolbars[index].items;
                        for (i = 0; i < items.length; i++) {
                            instance = items[i];
                            if (instance.clickFn)
                                CKEDITOR.tools.removeFunction(instance.clickFn);
                            if (instance.keyDownFn)
                                CKEDITOR.tools.removeFunction(instance.keyDownFn);
                        }
                    }
                }
            });

            // Manage editor focus  when navigating the toolbar.
            editor.on('uiReady', function () {
                var toolbox = editor.ui.space('toolbox');
                toolbox && editor.focusManager.add(toolbox, 1);
            });

            editor.addCommand('toolbarFocus', commands.toolbarFocus);
            editor.setKeystroke(CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus');

            editor.ui.add('-', CKEDITOR.UI_SEPARATOR, {});
            editor.ui.addHandler(CKEDITOR.UI_SEPARATOR, {
                create: function () {
                    return {
                        render: function (editor, output) {
                            output.push('<span class="cke_toolbar_separator" role="separator"></span>');
                            return {};
                        }
                    };
                }
            });
        }
    });

    function getToolbarConfig(editor) {
        var removeButtons = editor.config.removeButtons;

        removeButtons = removeButtons && removeButtons.split(',');

        function buildToolbarConfig() {

            // Object containing all toolbar groups used by ui items.
            var lookup = getItemDefinedGroups();

            // Take the base for the new toolbar, which is basically a toolbar
            // definition without items.
            var toolbar = CKEDITOR.tools.clone(editor.config.toolbarGroups) || getPrivateToolbarGroups(editor);

            // Fill the toolbar groups with the available ui items.
            for (var i = 0; i < toolbar.length; i++) {
                var toolbarGroup = toolbar[i];

                // Skip toolbar break.
                if (toolbarGroup == '/')
                    continue;
                // Handle simply group name item.
                else if (typeof toolbarGroup == 'string')
                    toolbarGroup = toolbar[i] = {name: toolbarGroup};

                var items, subGroups = toolbarGroup.groups;

                // Look for items that match sub groups.
                if (subGroups) {
                    for (var j = 0, sub; j < subGroups.length; j++) {
                        sub = subGroups[j];

                        // If any ui item is registered for this subgroup.
                        items = lookup[sub];
                        items && fillGroup(toolbarGroup, items);
                    }
                }

                // Add the main group items as well.
                items = lookup[toolbarGroup.name];
                items && fillGroup(toolbarGroup, items);
            }

            return toolbar;
        }

        // Returns an object containing all toolbar groups used by ui items.
        function getItemDefinedGroups() {
            var groups = {},
                itemName, item, itemToolbar, group, order;

            for (itemName in editor.ui.items) {
                item = editor.ui.items[itemName];
                itemToolbar = item.toolbar || 'others';
                if (itemToolbar) {
                    // Break the toolbar property into its parts: "group_name[,order]".
                    itemToolbar = itemToolbar.split(',');
                    group = itemToolbar[0];
                    order = parseInt(itemToolbar[1] || -1, 10);

                    // Initialize the group, if necessary.
                    groups[group] || (groups[group] = []);

                    // Push the data used to build the toolbar later.
                    groups[group].push({name: itemName, order: order});
                }
            }

            // Put the items in the right order.
            for (group in groups) {
                groups[group] = groups[group].sort(function (a, b) {
                    return a.order == b.order ? 0 :
                        b.order < 0 ? -1 :
                            a.order < 0 ? 1 :
                                a.order < b.order ? -1 :
                                    1;
                });
            }

            return groups;
        }

        function fillGroup(toolbarGroup, uiItems) {
            if (uiItems.length) {
                if (toolbarGroup.items)
                    toolbarGroup.items.push(editor.ui.create('-'));
                else
                    toolbarGroup.items = [];

                var item, name;
                while ((item = uiItems.shift())) {
                    name = typeof item == 'string' ? item : item.name;

                    // Ignore items that are configured to be removed.
                    if (!removeButtons || CKEDITOR.tools.indexOf(removeButtons, name) == -1) {
                        item = editor.ui.create(name);

                        if (!item)
                            continue;

                        if (!editor.addFeature(item))
                            continue;

                        toolbarGroup.items.push(item);
                    }
                }
            }
        }

        function populateToolbarConfig(config) {
            var toolbar = [],
                i, group, newGroup;

            for (i = 0; i < config.length; ++i) {
                group = config[i];
                newGroup = {};

                if (group == '/')
                    toolbar.push(group);
                else if (CKEDITOR.tools.isArray(group)) {
                    fillGroup(newGroup, CKEDITOR.tools.clone(group));
                    toolbar.push(newGroup);
                } else if (group.items) {
                    fillGroup(newGroup, CKEDITOR.tools.clone(group.items));
                    newGroup.name = group.name;
                    toolbar.push(newGroup);
                }
            }

            return toolbar;
        }

        var toolbar = editor.config.toolbar;

        // If it is a string, return the relative "toolbar_name" config.
        if (typeof toolbar == 'string')
            toolbar = editor.config['toolbar_' + toolbar];

        return (editor.toolbar = toolbar ? populateToolbarConfig(toolbar) : buildToolbarConfig());
    }

    /**
     * Adds a toolbar group. See {@link CKEDITOR.config#toolbarGroups} for more details.
     *
     * **Note:** This method will not modify toolbar groups set explicitly by
     * {@link CKEDITOR.config#toolbarGroups}. It will only extend the default setting.
     *
     * @param {String} name Toolbar group name.
     * @param {Number/String} previous The name of the toolbar group after which this one
     * should be added or `0` if this group should be the first one.
     * @param {String} [subgroupOf] The name of the parent group.
     * @member CKEDITOR.ui
     */
    CKEDITOR.ui.prototype.addToolbarGroup = function (name, previous, subgroupOf) {
        // The toolbarGroups from the privates is the one we gonna use for automatic toolbar creation.
        var toolbarGroups = getPrivateToolbarGroups(this.editor),
            atStart = previous === 0,
            newGroup = {name: name};

        if (subgroupOf) {
            // Transform the subgroupOf name in the real subgroup object.
            subgroupOf = CKEDITOR.tools.search(toolbarGroups, function (group) {
                return group.name == subgroupOf;
            });

            if (subgroupOf) {
                !subgroupOf.groups && (subgroupOf.groups = []);

                if (previous) {
                    // Search the "previous" item and add the new one after it.
                    previous = CKEDITOR.tools.indexOf(subgroupOf.groups, previous);
                    if (previous >= 0) {
                        subgroupOf.groups.splice(previous + 1, 0, name);
                        return;
                    }
                }

                // If no previous found.

                if (atStart)
                    subgroupOf.groups.splice(0, 0, name);
                else
                    subgroupOf.groups.push(name);
                return;
            } else {
                // Ignore "previous" if subgroupOf has not been found.
                previous = null;
            }
        }

        if (previous) {
            // Transform the "previous" name into its index.
            previous = CKEDITOR.tools.indexOf(toolbarGroups, function (group) {
                return group.name == previous;
            });
        }

        if (atStart)
            toolbarGroups.splice(0, 0, name);
        else if (typeof previous == 'number')
            toolbarGroups.splice(previous + 1, 0, newGroup);
        else
            toolbarGroups.push(name);
    };

    function getPrivateToolbarGroups(editor) {
        return editor._.toolbarGroups || (editor._.toolbarGroups = [
            {name: 'document', groups: ['mode', 'document', 'doctools']},
            {name: 'clipboard', groups: ['clipboard', 'undo']},
            {name: 'editing', groups: ['find', 'selection', 'spellchecker']},
            {name: 'forms'},
            '/',
            {name: 'basicstyles', groups: ['basicstyles', 'cleanup']},
            {name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align', 'bidi']},
            {name: 'links'},
            {name: 'insert'},
            '/',
            {name: 'styles'},
            {name: 'colors'},
            {name: 'tools'},
            {name: 'others'},
            {name: 'about'}
        ]);
    }
})();

/**
 * Separator UI element.
 *
 * @readonly
 * @property {String} [='separator']
 * @member CKEDITOR
 */
CKEDITOR.UI_SEPARATOR = 'separator';

/**
 * The part of the user interface where the toolbar will be rendered. For the default
 * editor implementation, the recommended options are `'top'` and `'bottom'`.
 *
 * Please note that this option is only applicable to [classic](#!/guide/dev_framed)
 * (`iframe`-based) editor. In case of [inline](#!/guide/dev_inline) editor the toolbar
 * position is set dynamically depending on the position of the editable element on the screen.
 *
 *        config.toolbarLocation = 'bottom';
 *
 * @cfg
 * @member CKEDITOR.config
 */
CKEDITOR.config.toolbarLocation = 'top';

/**
 * The toolbox (alias toolbar) definition. It is a toolbar name or an array of
 * toolbars (strips), each one being also an array, containing a list of UI items.
 *
 * If set to `null`, the toolbar will be generated automatically using all available buttons
 * and {@link #toolbarGroups} as a toolbar groups layout.
 *
 *        // Defines a toolbar with only one strip containing the "Source" button, a
 *        // separator, and the "Bold" and "Italic" buttons.
 *        config.toolbar = [
 *            [ 'Source', '-', 'Bold', 'Italic' ]
 *        ];
 *
 *        // Similar to the example above, defines a "Basic" toolbar with only one strip containing three buttons.
 *        // Note that this setting is composed by "toolbar_" added to the toolbar name, which in this case is called "Basic".
 *        // This second part of the setting name can be anything. You must use this name in the CKEDITOR.config.toolbar setting
 *        // in order to instruct the editor which `toolbar_(name)` setting should be used.
 *        config.toolbar_Basic = [
 *            [ 'Source', '-', 'Bold', 'Italic' ]
 *        ];
 *        // Load toolbar_Name where Name = Basic.
 *        config.toolbar = 'Basic';
 *
 * @cfg {Array/String} [toolbar=null]
 * @member CKEDITOR.config
 */

/**
 * The toolbar groups definition.
 *
 * If the toolbar layout is not explicitly defined by the {@link #toolbar} setting, then
 * this setting is used to group all defined buttons (see {@link CKEDITOR.ui#addButton}).
 * Buttons are associated with toolbar groups by the `toolbar` property in their definition objects.
 *
 * New groups may be dynamically added during the editor and plugin initialization by
 * {@link CKEDITOR.ui#addToolbarGroup}. This is only possible if the default setting was used.
 *
 *        // Default setting.
 *        config.toolbarGroups = [
 *            { name: 'document',	   groups: [ 'mode', 'document', 'doctools' ] },
 *            { name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },
 *            { name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
 *            { name: 'forms' },
 *            '/',
 *            { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
 *            { name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
 *            { name: 'links' },
 *            { name: 'insert' },
 *            '/',
 *            { name: 'styles' },
 *            { name: 'colors' },
 *            { name: 'tools' },
 *            { name: 'others' },
 *            { name: 'about' }
 *        ];
 *
 * @cfg {Array} [toolbarGroups=see example]
 * @member CKEDITOR.config
 */

/**
 * Whether the toolbar can be collapsed by the user. If disabled, the Collapse Toolbar
 * button will not be displayed.
 *
 *        config.toolbarCanCollapse = true;
 *
 * @cfg {Boolean} [toolbarCanCollapse=false]
 * @member CKEDITOR.config
 */

/**
 * Whether the toolbar must start expanded when the editor is loaded.
 *
 * Setting this option to `false` will affect the toolbar only when
 * {@link #toolbarCanCollapse} is set to `true`:
 *
 *        config.toolbarCanCollapse = true;
 *        config.toolbarStartupExpanded = false;
 *
 * @cfg {Boolean} [toolbarStartupExpanded=true]
 * @member CKEDITOR.config
 */

/**
 * When enabled, causes the *Arrow* keys navigation to cycle within the current
 * toolbar group. Otherwise the *Arrow* keys will move through all items available in
 * the toolbar. The *Tab* key will still be used to quickly jump among the
 * toolbar groups.
 *
 *        config.toolbarGroupCycling = false;
 *
 * @since 3.6
 * @cfg {Boolean} [toolbarGroupCycling=true]
 * @member CKEDITOR.config
 */

/**
 * List of toolbar button names that must not be rendered. This will also work
 * for non-button toolbar items, like the Font drop-down list.
 *
 *        config.removeButtons = 'Underline,JustifyCenter';
 *
 * This configuration option should not be overused. The recommended way is to use the
 * {@link CKEDITOR.config#removePlugins} setting to remove features from the editor
 * or even better, [create a custom editor build](http://ckeditor.com/builder) with
 * just the features that you will use.
 * In some cases though, a single plugin may define a set of toolbar buttons and
 * `removeButtons` may be useful when just a few of them are to be removed.
 *
 * @cfg {String} [removeButtons]
 * @member CKEDITOR.config
 */

/**
 * The toolbar definition used by the editor. It is created from the
 * {@link CKEDITOR.config#toolbar} option if it is set or automatically
 * based on {@link CKEDITOR.config#toolbarGroups}.
 *
 * @readonly
 * @property {Object} toolbar
 * @member CKEDITOR.editor
 */
